//
// Created by TNJ on 2021/6/7.
//

#include <stdio.h>
#include <stdlib.h>
#include "dlist.h"

dlist_t *new_dlist_node(int data){
    dlist_t *node = (dlist_t *)malloc(sizeof(dlist_t));
    if(node == NULL){
        return NULL;
    }

    node->data = data;
    node->next = node;
    node->prev = node;

    return node;
}

void free_dlist_node(dlist_t *node){
    if(node == NULL){
        return;
    }

    node->next = NULL;
    node->prev = NULL;
    free(node);
    node = NULL;
}

dlist_t *dlist_add(dlist_t *list, int data){
    if(list == NULL){
        return NULL;
    }

    //新建一个结点
    dlist_t *node = new_dlist_node(data);
    if(node == NULL){
        return list;
    }

    //将结点插入双向循环链表
    list->prev->next = node;
    node->next = list;
    node->prev = list->prev;
    list->prev = node;

    return list;
}

dlist_t *dlist_delete(dlist_t *list, int index){
    if(list == NULL || index < 0){
        return list;
    }

    dlist_t *head = list;
    int list_index = 0;

    //删除链表头结点
    if(index == 0){
        //链表只有一个结点
        if(head == list->next){
            free_dlist_node(list);
            list = NULL;
            return NULL;
        }else{
            //链表有大于1个结点
            head = head->next;  //头结点往后移一个
            head->prev = list->prev;  //头结点的prev指向尾部结点
            list->prev->next = head;  //尾部结点的next指针指向头结点
            free_dlist_node(list);  //释放结点内存
            return head;
        }
    }

    list = list->next;
    list_index++;

    //查询目标结点，通过检查当前结点是否是头结点判断是否已经把双线循环链表遍历了一遍
    while(list_index < index && head != list){
        list = list->next;
        list_index++;
    }
    //没有找到即将删除的结点
    if(head == list){
        return head;
    }
    //找到即将删除的结点
    else{
        list->prev->next = list->next;  //目标结点的上一个结点的next指针指向目标结点的下一个结点
        list->next->prev = list->prev;  //目标结点的下一个结点的prev指针指向目标结点的上一个结点
        free_dlist_node(list);  //释放结点内存
        return head;  //返回头结点
    }
}

dlist_t *dlist_index_of(dlist_t *list, int index){
    if(list == NULL || index < 0){
        return NULL;
    }

    //如果想要获取头结点，则直接返回头结点
    if(index == 0){
        return list;
    }

    dlist_t *head = list;
    list = list->next;
    int list_index = 1;
    //遍历链表查找指定的索引，通过检查当前结点是否等于头结点判断是否已遍历完毕
    while(list_index < index && list != head){
        list_index++;
        list = list->next;
    }
    //没有找到索引对应的结点
    if(list == head){
        return NULL;
    }
    //找到了索引对应的结点
    return list;
}

void dlist_destroy(dlist_t *list){
    if(list == NULL){
        return;
    }

    //如果只有一个结点
    if(list->next == list){
        free_dlist_node(list);
        return;
    }

    dlist_t *temp = list;
    list = list->next;
    while(list != temp){
        list = list->next;  //遍历下一个结点
        temp->prev->next = list;
        list->prev = temp->prev;
        temp->next = NULL;
        temp->prev = NULL;
        free(temp);
        temp = list;
    }

    free_dlist_node(list);
}

void dlist_print(dlist_t *list){
    if(list == NULL){
        return;
    }

    dlist_t *head = list;
    printf("%d, ", list->data);
    list = list->next;
    while(list != head){
        printf("%d, ", list->data);
        list = list->next;
    }
    printf("\n");
}